﻿#ifndef CQWTPLOTWIDGET_H
#define CQWTPLOTWIDGET_H

#include <QtQuick>
#include <qwt_plot_curve.h>
#include <qwt_plot.h>
#include <qwt_scale_draw.h>
class QwtScaleDiv;
class QwtPlotMarker;
class CMyPlotZoomers;
class QwtPlotGrid;
class QwtScaleDraw;

class CustomScaleDraw : public QwtScaleDraw
{
    public:
        CustomScaleDraw(const QString &strAxis, int iDigit):m_strAxis(strAxis)
        {
            if(m_strAxis=="X")
                m_iXDigit = iDigit;
            else
                m_iYDigit = iDigit;
        }

        virtual QwtText label(double value) const {
            if(m_strAxis=="X")
                return QString::number(value,  'f', m_iXDigit);  // 自定义标签格式
            else
                return QString::number(value,  'f', m_iYDigit);  // 自定义标签格式
        }
    private:
        int m_iXDigit = 3;
        int m_iYDigit = 2;
        QString m_strAxis = "X";
};

class CQwtPlotWidget : public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(QColor curveColor READ curveColor NOTIFY SignalcurveColorChanged)
    Q_PROPERTY(QStringList curveNames READ curveNames)
    Q_PROPERTY(qint16 curveNumber READ curveNumber)
    Q_PROPERTY(QColor pointColor READ pointColor WRITE setPointColor)
    Q_PROPERTY(QString xAxisName READ xAxisName WRITE setXAxisName NOTIFY SignalTitleInfoChanged)
    Q_PROPERTY(QString yAxisName READ yAxisName WRITE setYAxisName NOTIFY SignalTitleInfoChanged)
    Q_PROPERTY(QString axisFont READ axisFont WRITE setAxisFont NOTIFY SignalTitleInfoChanged)
    Q_PROPERTY(int axisSize READ axisSize WRITE setAxisSize NOTIFY SignalTitleInfoChanged)
    Q_PROPERTY(double xMin READ xMin WRITE setXMin NOTIFY signalAxisParameterChanged)
    Q_PROPERTY(double xMax READ xMax WRITE setXMax NOTIFY signalAxisParameterChanged)
    Q_PROPERTY(double yMin READ yMin WRITE setYMin NOTIFY signalAxisParameterChanged)
    Q_PROPERTY(double yMax READ yMax WRITE setYMax NOTIFY signalAxisParameterChanged)
    Q_PROPERTY(int xTickCount READ xTickCount WRITE setXTickCount)
    Q_PROPERTY(int yTickCount READ yTickCount WRITE setYTickCount)
    Q_PROPERTY(int xAxisDigit READ xAxisDigit WRITE setXAxisDigit)
    Q_PROPERTY(int yAxisDigit READ yAxisDigit WRITE setYAxisDigit)
    Q_PROPERTY(bool showLegend READ showLegend WRITE setShowLegend NOTIFY signalLegendChanged)
    Q_PROPERTY(bool zoomEnabled READ isZoomEnabled WRITE setZoomEnabled)
    Q_PROPERTY(bool symbolVisible READ getSymbolVisible WRITE setSymbolVisible)
    Q_PROPERTY(bool smoothCurves READ getSmoothCurves WRITE setSmoothCurves NOTIFY signalCurverSmoothChanged)
    Q_PROPERTY(QVariant model READ model WRITE setModel)


public:
    explicit CQwtPlotWidget(QQuickItem *parent = NULL);
    ~CQwtPlotWidget();
    void paint(QPainter *painter);
    void initQwtPlot(QwtPlot* m_pQwtPlot);

    Q_INVOKABLE void setXAxisName(const QString& title);
    Q_INVOKABLE void setYAxisName(const QString& title);
    Q_INVOKABLE void setCurveWidth(const double &width);
    void setCurveWidth(const QString& curveName, const double &width);
    Q_INVOKABLE void setCurveColor(const QString& curveName, const QColor &color);
    Q_INVOKABLE void setLogScale();
    Q_INVOKABLE void setLinearScale();
    Q_INVOKABLE void addCurve(const QString &curvelName);
    Q_INVOKABLE void addPoint(const QString &curvelName, const qreal &x, const qreal &y, bool isUpdate=true);
    Q_INVOKABLE void addPoint(const QString &curvelName, const qreal &x, const qreal &y,
                              const QString &curvelType);
    Q_INVOKABLE void visibleCurve(const QString &strCurvelName, bool bVisible);
    Q_INVOKABLE void deleteCurveData();
    Q_INVOKABLE void changeCurrentCurvel(const QString &curvelName);
    Q_INVOKABLE void changeShowLegend();
    Q_INVOKABLE void exportTECDataToCSV(const QString& strFileName);
    Q_INVOKABLE void exportFluoDataToCSV(const QString& strFileName);
    Q_INVOKABLE void importDataFromCSV(const QString& strFilename);
    QColor pointColor();
    void setPointColor(const QColor &m_iPointColor);
    QStringList curveNames() const {
        return m_pPlotCurvelsMap.keys();
    }
    QColor curveColor() const {
        return  m_pPlotCurvelsMap[m_strCurrentCurvelName]->pen().color();  // 获取当前的颜色
    }
    qint16 curveNumber() const{
        return m_iPlotCurveCount;
    }
    QString xAxisName() const { return m_strXAxisName; }
    QString yAxisName() const { return m_strYAxisName; }
    QString axisFont() const { return m_strAxisFont; }
    void setAxisFont(const QString &strAxisFont);
    int axisSize() const { return m_iAxisSize; }
    void setAxisSize(const int &iAxisSize);
    double xMin() const { return m_dXMin; }
    void setXMin(double value){
        if (m_dXMin != value){
            m_dXMin = value;
            emit signalAxisParameterChanged();
        }
    }

    double xMax() const { return m_dXMax; }
    void setXMax(double value){
        if (m_dXMax != value){
            m_dXMax = value;
            emit signalAxisParameterChanged();
        }
    }

    double yMin() const { return m_dYMin; }
    void setYMin(double value){
        if (m_dYMin != value){
            m_dYMin = value;
            emit signalAxisParameterChanged();
        }
    }

    double yMax() const { return m_dYMax; }
    void setYMax(double value){
        if (m_dYMax != value){
            m_dYMax = value;
            emit signalAxisParameterChanged();
        }
    }

    int xTickCount() const { return m_iXTickCount; }
    void setXTickCount(int value){
        if (m_iXTickCount != value){
            m_iXTickCount = value;
            _SetAxisRange(QwtPlot::xBottom, m_dXMin, m_dXMax, true);
        }
    }

    int yTickCount() const { return m_iYTickCount; }
    void setYTickCount(int value){
        if (m_iYTickCount != value){
            m_iYTickCount = value;
            _SetAxisRange(QwtPlot::yLeft, m_dXMin, m_dXMax, true);
        }
    }
    bool showLegend() const { return m_bShowLegend; }

    void setShowLegend(bool value) {
        if (m_bShowLegend != value) {
            m_bShowLegend = value;
            emit signalLegendChanged();
        }
    }

    void setZoomEnabled(bool enabled) { m_bZoomEnabled = enabled; }
    bool isZoomEnabled() const { return m_bZoomEnabled; }

    bool getSymbolVisible()const{return m_bSymbolVisible;}
    void setSymbolVisible(bool bVisible);

    bool getSmoothCurves()const{return m_bSmoothCurves;}
    void setSmoothCurves(bool bSmoothCurves);

    QVariant model() const { return m_vModel;}
    void setModel(const QVariant &model);

    int xAxisDigit() const
    {
        return m_iXAxisDigit;
    }

    int yAxisDigit() const
    {
        return m_iYAxisDigit;
    }

public slots:
    void setXAxisDigit(int xAxisDigit);

    void setYAxisDigit(int yAxisDigit);

protected:
    virtual void mousePressEvent(QMouseEvent* event);
    virtual void mouseReleaseEvent(QMouseEvent* event);
    virtual void mouseMoveEvent(QMouseEvent* event);
    virtual void hoverMoveEvent(QHoverEvent *event);

private:
    CMyPlotZoomers* m_pPlotZoom = NULL;
    QwtPlot* m_pQwtPlot = NULL;
    QwtScaleDiv *m_pXAxis=NULL;
    QwtScaleDiv *m_pYAxis=NULL;
    QwtPlotMarker *m_pCurvelMarker=NULL;
    QwtPlotGrid* m_pGrid = NULL;
    QMap<QString,QwtPlotCurve* > m_pPlotCurvelsMap;
    qint16 m_iPlotCurveCount = 0;
    int m_iAxisSize = 12;
    double m_dXMin = 0;
    double m_dXMax = 100000;
    double m_dYMin = 0;
    double m_dYMax = 100;
    double m_dClosestPointX = -1;
    double m_dClosestPointY = -1;
    int m_iXTickCount = 10;
    int m_iYTickCount = 20;
    int m_iCurveWidth = 3;
    int m_iXAxisDigit = 3;
    int m_iYAxisDigit = 2;
    QString m_strCurrentCurvelName;
    QString m_strXAxisName = "X";
    QString m_strYAxisName = "Y";
    QString m_strAxisFont = "Arial";
    QString m_strClosestCurveName = "";
    QString m_strExportDataDir = "";
    bool m_bShowLegend = false;
    bool m_bZoomEnabled=false;
    bool m_bSymbolVisible = true;
    bool m_bSmoothCurves = false;
    QRect m_iZoomRectangleRect;
    QColor m_iPointColor=Qt::red;
    QVariant m_vModel;
    void _ReplotAndUpdate();
    void _ShouldUpdateAxisRange(const double &x, const double &y);
    void _SetAxisRange(QwtPlot::Axis axis, double dMinValue, double dMaxValue,
                       bool bUpdateTickCount=false);

private slots:
    void _SlotUpdatePlotSize();
    void _SlotUpdateTitle();
    void _slotUpdateAxis();
    void _slotUpdateLegend();

signals:
    void SignalcurveColorChanged();
    void SignalTitleInfoChanged();
    void signalAxisParameterChanged();
    void signalLegendChanged();
    void signalCurverSmoothChanged();
    void signalGetClosestPointValue(QString strCurveName, double dX, double dY);
};

#endif // CQWTPLOTWIDGET_H
